// -*- coding: UTF-8 -*-
// utf-8编译
// javac -encoding UTF-8 Calculator.java

// # 基础打包（无主类）
// jar cvf Calculator.jar  Calculator.class

import java.util.Scanner; 
import java.util.ArrayDeque; 
import java.util.Deque; 
 
public class Calculator {

    public static void main(String[] args) {
		
        Scanner scanner = new Scanner(System.in); 
        System.out.println("🧮  Java 控制台计算器");
        System.out.println("════════════════════"); 
        System.out.println(" 支持操作: +, -, *, /");
        System.out.println(" 输入格式: 数字 运算符 数字 (如: 2 + 3 * 4)");
        System.out.println(" 输入 'exit' 退出程序");
        System.out.println("════════════════════"); 
 
        while (true) {
            System.out.print("➤  输入表达式: ");
            String input = scanner.nextLine().trim(); 
            
            if (input.equalsIgnoreCase("exit"))  {
                System.out.println("🛑  程序已退出");
                break;
            }
            
            if (input.isEmpty())  {
                System.out.println("⚠️  错误：输入不能为空");
                continue;
            }
            
            try {
                double result = evaluateExpression(input);
                System.out.printf("✅  计算结果: %s = %.2f\n\n", input, result);
            } catch (Exception e) {
                System.out.println("❌  错误: " + e.getMessage()); 
            }
        }
        scanner.close(); 
    }
 
    /**
     * 计算表达式值（支持运算符优先级）
     * @param expression 数学表达式 
     * @return 计算结果
     * @throws IllegalArgumentException 非法输入时抛出异常 
     */
    public static double evaluateExpression(String expression) {
        // 移除所有空格
        String expr = expression.replaceAll("\\s+",  "");
        
        // 检查非法字符
        if (!expr.matches("[\\d.+\\-*/]+")) {
            throw new IllegalArgumentException("包含非法字符");
        }
        
        Deque<Double> numbers = new ArrayDeque<>();
        Deque<Character> operators = new ArrayDeque<>();
        
        for (int i = 0; i < expr.length();  i++) {
            char c = expr.charAt(i); 
            
            // 处理数字（包括小数）
            if (Character.isDigit(c)  || c == '.') {
                StringBuilder numBuilder = new StringBuilder();
                while (i < expr.length()  && 
                      (Character.isDigit(expr.charAt(i)) || expr.charAt(i) == '.')) {
                    numBuilder.append(expr.charAt(i++)); 
                }
                i--; // 回退一步 
                
                try {
                    double number = Double.parseDouble(numBuilder.toString()); 
                    numbers.push(number); 
                } catch (NumberFormatException e) {
                    throw new IllegalArgumentException("无效数字格式: " + numBuilder);
                }
				
            } 
            
			// 处理运算符 
            else if (isOperator(c)) {
                while (!operators.isEmpty()  && 
                      hasPrecedence(c, operators.peek()))  {
                    calculateTop(numbers, operators);
                }
                operators.push(c); 
            } else {
                throw new IllegalArgumentException("无效字符: " + c);
            }
        }
		
        
        // 计算剩余操作 
        while (!operators.isEmpty())  {
            calculateTop(numbers, operators);
        }
        
        if (numbers.size()  != 1 || !operators.isEmpty())  {
            throw new IllegalArgumentException("无效表达式格式");
        }
        
        return numbers.pop(); 
    }
 
    /**
     * 执行栈顶运算 
     */
    private static void calculateTop(Deque<Double> numbers, Deque<Character> operators) {
        if (numbers.size()  < 2 || operators.isEmpty())  {
            throw new IllegalArgumentException("运算符缺失");
        }
        
        double b = numbers.pop(); 
        double a = numbers.pop(); 
        char op = operators.pop(); 
        
        switch (op) {
            case '+': numbers.push(a  + b); break;
            case '-': numbers.push(a  - b); break;
            case '*': numbers.push(a  * b); break;
            case '/': 
                if (b == 0) throw new ArithmeticException("除零错误");
                numbers.push(a  / b); 
                break;
            default: throw new IllegalArgumentException("不支持的操作符: " + op);
        }
    }
 
    /**
     * 检查运算符优先级 
     * @param current 当前运算符 
     * @param previous 栈顶运算符 
     * @return 当前运算符是否优先级较低或相等
     */
    private static boolean hasPrecedence(char current, char previous) {
        if (previous == '(' || previous == ')') return false;
        return (current != '*' && current != '/') || 
               (previous != '+' && previous != '-');
    }
 
    private static boolean isOperator(char c) {
        return c == '+' || c == '-' || c == '*' || c == '/';
    }
}